package controllers;
import java.io.File;
import java.io.IOException;
import java.sql.SQLException;
import java.util.Date;
import javax.swing.JOptionPane;
import javax.swing.JPanel;

import Entity.BookCopy;
import Entity.User;
import messagesPacks.*;
import messagesPacks.GenericMessage.msgType;
import files.Browse;
import files.MyFile;
import files.Save;
import gui.ServerUI;
import gui.WelcomeUI;
import ocsf.server.ConnectionToClient;

/**
 * This class represents all the operations at the server side.
 * @author Alon Shahaf
 * @Date 01.01.2013
 */	

public class ServerUIP extends JPanel
{
	private static final long serialVersionUID = 1L;
	private ServerUI UILayer; 
	private EchoServer eServer;
	private DBController db;
	public static IntSysClock clk;
	private JobsManager jobMngr;
	
	final public static int EXIT = 1;
	final public static int START = 2;
	final public static int STOP = 3;
	final public static int KeyRelease_DB_Port = 4;
	final public static int KeyRelease_DB_User = 5;
	final public static int KeyRelease_DB_Pass = 6;
	final public static int KeyRelease_DB_Name = 7;
	final public static int KeyRelease_DB_IP = 8;
	final public static int KeyRelease_Port = 9;
	final public static int KeyRelease_Limit = 10;
	
	public ServerUIP(ServerUI sui)
	{
		this.setUILayer(sui);
		clk = new IntSysClock();						// Create a new Internal System Clock.
		jobMngr = new JobsManager(OBLSettings.HOUR,OBLSettings.MIN,OBLSettings.SEC,OBLSettings.MS,OBLSettings.INTERVAL); // Start Jobs Manager to run every day in 08:00.
		System.out.println("UIP@Server: created.");
	}

	public ServerUI getUILayer() 
	{
		return UILayer;
	}

	private void setUILayer(ServerUI uILayer) 
	{
		UILayer = uILayer;
	}
//=================================================================================
	/**
	 * This function checks if the server services are running.
	 * @author Alon Shahaf
	 * @Date 10.01.2013
	 */	
	public boolean isServerRunning()
	{
		if (!db.isClosed() && !eServer.isClosed()) return true;
		return false;
	}
//=================================================================================
	/**
	 * @author Alon Shahaf
	 * @Date 01.01.2013
	 */	
	public void start()
	{
		int res_conns;
		System.out.println("UIP@Server: START clicked/");
		UILayer.setStopEnable(true);
		UILayer.setStartEnable(false);
		UILayer.setExitEnable(false);
		// Check all fields to be filled out correctly.
		// ......
		
		UILayer.msgConsole("Starting service..");
		
		try
		{
			this.eServer = new EchoServer(UILayer.getPort(),this);
			String str_DB_Password = new String(UILayer.getDBPassword());
			this.db = new DBController( UILayer.getDBIP() , UILayer.getDBPort() 
					,UILayer.getDBUsername() , str_DB_Password , UILayer.getDBSchemeName());
			
			if ((res_conns=resetOldConnections()) > 0) 
				UILayer.msgConsole("UIP@Server: (start) " + res_conns + " connections has been restarted.");	
			eServer.listen(); //Start listening for connections
			if (!jobMngr.isRunning())
			{
				jobMngr.setDB(db);
				jobMngr.setClock(clk);
				jobMngr.setEcho(eServer);
				jobMngr.startCycle();
			}
			// Disable settings options
			UILayer.setSettings(false);
		}
		catch (IOException ioex) 
		{
			UILayer.setStopEnable(false);
			UILayer.setStartEnable(true);
			UILayer.setExitEnable(true);
			UILayer.msgConsole("ERROR - Could not start listening!");
		}
//		catch (InstantiationException | ClassNotFoundException | IllegalAccessException e) 
//		{
//			UILayer.setStopEnable(false);
//			UILayer.setStartEnable(true);
//			UILayer.setExitEnable(true);
//			UILayer.msgConsole("ERROR - JDBC Driver error!");			
//		}
		catch (SQLException e) 
		{
			UILayer.setStopEnable(false);
			UILayer.setStartEnable(true);
			UILayer.setExitEnable(true);
			UILayer.msgConsole("ERROR - Could not connect to DB using JDBC!");
		} 
		catch (InstantiationException e) 
		{
			UILayer.setStopEnable(false);
			UILayer.setStartEnable(true);
			UILayer.setExitEnable(true);
			UILayer.msgConsole("ERROR - JDBC Driver error!");
			e.printStackTrace();
		} 
		catch (IllegalAccessException e) 
		{
			UILayer.setStopEnable(false);
			UILayer.setStartEnable(true);
			UILayer.setExitEnable(true);
			UILayer.msgConsole("ERROR - JDBC Driver error!");
			e.printStackTrace();
		} 
		catch (ClassNotFoundException e) 
		{
			UILayer.setStopEnable(false);
			UILayer.setStartEnable(true);
			UILayer.setExitEnable(true);
			UILayer.msgConsole("ERROR - JDBC Driver error!");
			e.printStackTrace();
		}
	}
//=================================================================================	
	/**
	 * @author Alon Shahaf
	 * @Date 01.01.2013
	 */	
	public void stop()
	{
		UILayer.msgConsole("UIP@Server: STOP clicked.");
		UILayer.setStartEnable(true);
		UILayer.setExitEnable(true);
		UILayer.setStopEnable(false);
		try
		{
			if (jobMngr.isRunning())			// Stop all jobs.
				jobMngr.stopCycle();
			int dbclosed = -99;
			dbclosed = db.closeConnection();	// Close connection to DB
			if (dbclosed == 1)
				UILayer.msgConsole("Connection to DB closed successfuly.");
			else
				UILayer.msgConsole("Connection to DB failed to close!");
			eServer.close();		// Close server connection listener
			UILayer.msgConsole("All services were stopped.");
			// Enable settings options
			UILayer.setSettings(true);
		}
	    catch (IOException e) 
		{
			e.printStackTrace();
		}
	}
//=================================================================================	
	/**
	 * @author Alon Shahaf
	 * @Date 01.01.2013
	 */	
	public void exit()
	{
		System.out.println("UIP@Server: EXIT clicked");

		if (JOptionPane.showConfirmDialog(UILayer,"Are you sure?", "Quitting",JOptionPane.YES_NO_OPTION) == JOptionPane.YES_OPTION)
		{
			System.out.println("UIP@Server: EXIT event.");
			clk.saveIsysTime();
			try 
		    {
				if ((!eServer.isClosed()))
				{
					eServer.close();		 // Close server connection listener
					UILayer.msgConsole("Connection listener closed successfuly.");
				} 
				int dbclosed = -99;
				if(!db.isClosed())
					   dbclosed = db.closeConnection(); // Close connection to DB
				if (dbclosed == 1)
					UILayer.msgConsole("Connection to DB closed successfuly.");
				else
					UILayer.msgConsole("Connection to DB failed to close!");
		    }
			catch (IOException e) 
			{
					e.printStackTrace();
					UILayer.msgConsole("Connection listener failed to close!");
			}
			catch (NullPointerException e)
			{	
				System.exit(0);
			}
		  System.exit(0);
		}
	}

	/**
	 * Resets all the old connections at the client field.
	 * @author Alon Shahaf
	 * @Date 10.01.2013
	 * @return the number of connections that reseted.
	 */
	public int resetOldConnections()
	{
		if (eServer.isClosed())
			return db.resetOldConnections();
		return 0;
	}
//=================================================================================
	/**
	 * Handles a login message from a client.
	 * @author Alon Shahaf
	 * @Date 10.01.2013
	 * @param client is the connection to the client
	 * @param pass	the user password
	 */
	public void handleLogin(ConnectionToClient client,String user,String pass)
	{
		try 
		{
			LoginMessage loginMsg ;
			loginMsg = db.getLoginDataByIdAndPassword(user, pass);		
			client.sendToClient(loginMsg);
			System.out.println("Login Query OK - Result is " + loginMsg.getLoginResult());
		} 
		catch (IOException e) 
		{
			System.out.println("Login Query failed.");
		}
	}
//=================================================================================	
	/**
	 * @author Roman Faktorovich
	 * @Date 20.12.12
	 * This method handles books subjects request 
	 */
	public void handleSubjectBooksRequest(ConnectionToClient client)
	{
		try
		{
			BookSubjectMessage BookSubject_msg = new BookSubjectMessage();
			BookSubject_msg = db.getBooksSubjects();
			client.sendToClient(BookSubject_msg);
			System.out.println("get Books subjects Query OK ");
		}
		catch(IOException e)
		{
			System.out.println("get Books subjects Query failed ");
		}
		
	}
//=================================================================================	
	/**
	 * @author Roman Faktorovich
	 * @Date 19.12.12
	 * This method handles update user profile request 
	 */
	public void handleSubscUpdateProfileRequest(ConnectionToClient client,SubscriberUpdateProfileMessage SUPM)
	{
		try
		{
			SubscriberUpdateProfileMessage Update_msg = new SubscriberUpdateProfileMessage();
			int result = db.updateUserProfile(client,SUPM);
			Update_msg.setUpdateResult(result);
			System.out.println("Subscriber Update Profile Query OK - Result is "+ result);
			client.sendToClient(Update_msg);
			
		}
		catch(IOException e)
		{
			System.out.println("Subscriber Update Profile Query failed.");
		}
	}
//=================================================================================	
	/**
	 * @author Roman Faktorovich
	 * @Date 27.12.12
	 * This method handles search book request 
	 */
	public void handleSubscSearchBookRequest( ConnectionToClient client , SubscriberSearchBookMassege search_msg )
	{
		//SubscriberSearchBookMassege 
		SubscriberSearchBookMassege result_search_msg  ;
		try
		{
			System.out.println("UIP@Server: (handleSubscSearchBookRequest) ServerUIP > try query");
			result_search_msg = db.searchBook( client , search_msg );
			client.sendToClient(result_search_msg);
		}
		catch(IOException e)
		{
			System.out.println("UIP@Server: (handleSubscSearchBookRequest) Subscriber search book Query failed.");
		}
	}
//=================================================================================	
	/**
	 * @author Roman Faktorovich
	 * @Date 29.12.12
	 * This method handles view history request 
	 */
	
	public void handleSubsViewHistoryRequest(ConnectionToClient client , ViewHistoryMessage history_msg)
	{
		ViewHistoryMessage result_order;
			try
			{
				System.out.println("UIP@Server: ( handleSubsViewHistoryRequest) ServerUIP > try query");
				result_order = db.SubViewHistory( client ,history_msg );
				System.out.println("UIP@Server: (handleSubsViewHistoryRequest) Subscriber view history Query OK - Result is "+history_msg.getMsg_result());
				client.sendToClient(result_order);
			}
			catch(IOException e)
			{
				System.out.println("UIP@Server: (handleSubsViewHistoryRequest) Subscriber  view history Query failed.");
				
			}

	}
//=================================================================================	
	/**
	 * @author Roman Faktorovich
	 * @Date 02.01.13
	 * This method handles order a book request 
	 */
	public void handleSubscOrderBookRequest(ConnectionToClient client , BookOrderMessage order_msg )
	{
		 BookOrderMessage result_order;
			try
			{
				Date actualDate = clk.getTime();
				System.out.println("UIP@Server: ( handleSubscOrderBookRequest) ServerUIP > try query");
				result_order = db.orderABook( client , order_msg ,actualDate );
				System.out.println("UIP@Server: (handleSubscOrderBookRequest) Subscriber search book Query OK - Result is "+ result_order.getResultOforder());
				client.sendToClient(result_order);
			}
			catch(IOException e)
			{
				System.out.println("UIP@Server: (handleSubscSearchBookRequest) Subscriber search book Query failed.");
				
			}
	}
//=================================================================================	
	/**
	 * @author Roman Faktorovich
	 * @Date 12.01.13
	 * This method handles extracting borrow data request from subscriber
	 */
	public void handleSubscExtendRequest( ConnectionToClient client , SubscriberBorrowDataMessage  Extemsg )
	{
		try
		{
			 System.out.println("UIP@Server: ( handleSubscExtendRequest) ServerUIP > try query");
			 Extemsg = db.ExtractBorrowData( client ,  Extemsg );
			 System.out.println("UIP@Server: (handleSubscExtendRequest) SubExtendBorrow Query OK - Result is "+ Extemsg.msg_result);
			 client.sendToClient( Extemsg);
		}
		catch(IOException e)
		{
			System.out.println("UIP@Server: (handleSubscExtendRequest) SubExtendBorrow Query failed.");
			
		}
	}
//=================================================================================
	/**
	 * @author Roman Faktorovich
	 * @Date 12.01.13
	 * This method handles Extend borrow request from subscriber
	 */
	public void handleSubscExtendBorrowRequest(ConnectionToClient client , SubExtendBorrowMessage Ex_msg )
	{
		try
		{
			System.out.println("UIP@Server: ( handleSubscExtendRequest) ServerUIP > try query");
			Ex_msg = db.SubExtendBorrow(Ex_msg ,clk);
			System.out.println("UIP@Server: (handleSubscExtendRequest) SubExtendBorrow Query OK - Result is "+ Ex_msg.msg_result);
			client.sendToClient(Ex_msg);
		}
		catch(IOException e)
		{
			System.out.println("UIP@Server: (handleSubscExtendRequest) SubExtendBorrow Query failed.");
			
		}
		
	}
//=================================================================================
	/**
	 * @author Alon Shahaf
	 * @Date 01.01.2013
	 */	
	public int handleLogout(ConnectionToClient client,String user,String ip)
	{
		if (user.isEmpty() == false)
		{
			if (user == "Guest")
			{
				System.out.println("UIP@Server: (handleLogout) client Guest@" + client.getInetAddress().getHostAddress() + " closed connection.");
				return -1;
			}
			if (db.setUserStatus(user,0) == 1)
			{
				return 1;
			}
			return -1;
		}
		try 
		{
			LogoutMessage logoutMsg = new LogoutMessage(client.getInetAddress().getHostAddress());
			logoutMsg.setLogoutResult(-1);
			if (db.setUserStatus((String)client.getInfo("USER"),0) == 1)
				logoutMsg.setLogoutResult(1);	
			client.sendToClient(logoutMsg);
			return 1;
		}
		catch (IOException e) 
		{
			System.out.println("UIP@Server: (handleLogout) Logout Query failed for "+ client.getInetAddress().getHostAddress()+".");
		}
		return -1;
	}
//=================================================================================
	/**
	 * @author Alon Shahaf
	 * @Date 12.01.2013
	 */	
	public void handleGraduateUser(ConnectionToClient client, UsersMSG grad_msg)
	{
		// Prepare return message
		SimpleIntMessage returnMessage = new SimpleIntMessage(SimpleIntMessage.op_type.ADMIN_graduate,1);
		returnMessage.setResult(-99);
		try
		{
			String user_id = grad_msg.getUser(0).getID();
			System.out.println("UIP@Server: (handleGraduateUser) starting to handle graduate operation for user ID = "+user_id);
			int grad_result = -99;
			grad_result = db.graduateUser(user_id);
			returnMessage.setResult(grad_result);
			
 			// Disconnect user if graduated is OK and he is connected
 			if ((grad_result == 1) || (grad_result == 0))
 			{
 				System.out.println("UIP@Server: (handleGraduateUser) Forcing logout for user ID = "+user_id);
 				UILayer.msgConsole("UIP@Server: (handleGraduateUser) Forcing logout for user ID = "+user_id);
 				
 				// Go through all connected clients to find the locked user.
 				for (Thread c : eServer.getClientConnections())
 				{
 					ConnectionToClient s = (ConnectionToClient)c;
 					System.out.println("UIP@Server: (handleGraduateUser) CLIENT --> " +s.getInetAddress());
 					if (s.getInfo("USER").equals(user_id))
 					{
 						System.out.println("UIP@Server: (handleGraduateUser) FOUND LOCKED CLIENT --> " +s.getInetAddress());
 						if (s.isAlive())
 						{
 							System.out.println("UIP@Server: (handleGraduateUser) FOUND LOCKED ALIVE CLIENT --> " +s.getInetAddress());
 							s.close();
 						}
 					}
 				}	
 			}
 			
 			// Return message to sender.
 			client.sendToClient(returnMessage);
		}
		catch(IOException e)
		{
			System.out.println("UIP@Server: (handleGraduateUser) Query failed.");
		}
	}
	
//=================================================================================
	/**
	 * @author Alon Shahaf
	 * @Date 10.01.2013
	 */	
	public void handleListLockedUsers(ConnectionToClient client)
	{
		try
		{
			UsersMSG locked_msg;
			locked_msg = db.getLockedUsers();
			client.sendToClient(locked_msg);
		}
		catch(IOException e)
		{
			System.out.println("UIP@Server: (handleListLockedUsers) Query failed.");
		}
	}	
//=================================================================================
	/**
	 * @author Ariel Brucker
	 * @Date 10.01.2013
	 * @return employee list from DB
	 */	
	public void handleEmployeesList(ConnectionToClient client)
	{
		try
		{
			UsersMSG empList;
			empList=db.getAllEmployees();
			client.sendToClient(empList);
		}
		catch(IOException e)
		{
			System.out.println("UIP@Server: (handleEmployeesList) Query failed.");
		}
	}
	
//=================================================================================
	/**
	 * @author Ariel Brucker
	 * @Date 10.01.2013
	 * @return void
	 */	
	public void handleUnsuspendedSubs(ConnectionToClient client)
	{
		try
		{
			UsersMSG unSuspendedSubsList;
			unSuspendedSubsList=db.getAllUnsuspendedSubs();
			client.sendToClient(unSuspendedSubsList);
		}
		catch(IOException e)
		{
			System.out.println("UIP@Server: (handleEmployeesList) Query failed.");
		}
	}
//=================================================================================	
	/**
	 * @author Ariel Brucker
	 * @Date 10.01.2013
	 * 
	 * @return void
	 */	
	public void handleLateSubs(ConnectionToClient client)
	{
		try
		{
			UsersMSG LateSubsList;
			LateSubsList=db.getAllLateSubs();
			client.sendToClient(LateSubsList);
		}
		catch(IOException e)
		{
			System.out.println("UIP@Server: (handleLateSubs) Query failed.");
		}
	}
//=================================================================================	
	/**
	 * @author Ariel Brucker
	 * @Date 10.01.2013
	 * @return employee list from DB
	 */	
	public void handleSuspendSub(ConnectionToClient client,SuspendMSG suspendMSG)
	{
		try
		{
			System.out.println("UIP@Server: ( handleSuspendSub) ServerUIP > try query");
			SuspendMSG suspendMSGResult;
			suspendMSGResult=db.suspendSubscriber(client,suspendMSG);
			client.sendToClient(suspendMSG);
		}
		catch(IOException e)
		{
			System.out.println("UIP@Server: (handleSuspendSub) Query failed.");
		}
	}
//=================================================================================	
	/**
	 * @author Ariel Brucker
	 * @Date 10.01.2013
	 * @return void
	 */	
	public void handleManagerSerachSubMSG(ConnectionToClient client,ManagerSerachSubMSG managerSerachSubMSG)
	{
		ManagerSerachSubMSG managerSerachSubResultMSG;
		try
		{
		 System.out.println("UIP@Server: ( handleManagerSerachSubMSG) ServerUIP > try query");
		 managerSerachSubResultMSG=db.managersearchSubs(client,managerSerachSubMSG);
		 client.sendToClient(managerSerachSubResultMSG);
		}	
		catch(IOException e)
		{
			System.out.println("UIP@Server: (handleManagerSerachSubMSG) Query failed.");
		}
 	}
	
//=================================================================================	
	/**
	 * @author Ariel Brucker
	 * @Date 10.01.2013
	 * @return void
	 */	
	public void handleBorrowReportData(ConnectionToClient client)
	{
		BorrowStatisticsMSG borrowStatisticsMSG;
		try
		{
		 System.out.println("UIP@Server: ( handleBorrowReportData) ServerUIP > try query");
		 borrowStatisticsMSG=db.getBorrowReportData();
		 client.sendToClient(borrowStatisticsMSG);
		}	
		catch(IOException e)
		{
			System.out.println("UIP@Server: (handleBorrowReportData) Query failed.");
		}
 	}
//=================================================================================	
	/**
	 * @author Ariel Brucker
	 * @Date 10.01.2013
	 * @return void
	 */	
 public void handleLatenessReport(ConnectionToClient client)
 {
	 ManagerLatenessReportMSG managerLatenessReportMSG=null;
	 try
	 {
		 System.out.println("UIP@Server: ( handleLatenessReport) ServerUIP > start");
		 managerLatenessReportMSG=db.getLatenessReportData();
		 client.sendToClient(managerLatenessReportMSG);
	 }
	 catch(IOException e)
	 {
			System.out.println("UIP@Server: (handleLatenessReport) Query failed.");
	 }
 }
	
//=================================================================================
 /**
	 * @author Ariel Brucker
	 * @Date 10.01.2013
	 * @return void
	 */	

	public int handleUnlockUser(ConnectionToClient client, UsersMSG msg)
	{
		int user_status = -99;

		try 
		{	
			// Prepare return message
			SimpleIntMessage unlockMessage = new SimpleIntMessage(SimpleIntMessage.op_type.ADMIN_unlock,1);
			unlockMessage.setResult(-99);
						
			if (msg.getUser(0).getID().isEmpty() == false)
			{
				System.out.println("UIP@Server: (handleUnlockUser) - got unlock for ID = " + msg.getUser(0).getID());
				// Check if user not already locked
				user_status = db.getUserStatus(msg.getUser(0).getID());
				switch(user_status)
				{
					case 2: // User is locked
					{
						System.out.println("UIP@Server: (handleUnlockUser) ADMIN_unlock - user " + msg.getUser(0).getID() + " is locked, unlocking...");
						if (db.setUserStatus(msg.getUser(0).getID(), 0) == 1)
							unlockMessage.setResult(1);
						break;	
					}
					case -99: // Query error
					{
						System.out.println("UIP@Server: (handleUnlockUser) - QUERY ERROR!!!");
						break;
					}
					default: // User isn't locked
					{
						System.out.println("UIP@Server: (handleUnlockUser) - user " + msg.getUser(0).getID() + " isn't locked!!!");
						unlockMessage.setResult(0);
					}
				}
			}
			else
			{
				unlockMessage.setResult(-1);
			}
			// Send message back to client
			client.sendToClient(unlockMessage);
		}
		catch (IOException e)
		{
			System.out.println("UIP@Server: (handleUnlockUser) Query failed.");
		}
		return 0;
	}
//==============================================================================================
	/**
	 * This function gets a user details in the format of UserMSG package and creates him in the DB.
	 * The user to be created must be entered in the index 0 at the UserMSG HashTable.
	 * The function returns a 
	 * @author Alon Shahaf
	 * @Date 10.01.2013
	 * @return SimpleIntMessage containing the result field, -1 - the user already exists, 1 - success
	 */
	public void handleCreateUser(ConnectionToClient client, UsersMSG msg)
	{
		int create_result = -99;

		try 
		{	
			// Prepare return message
			SimpleIntMessage createMessage = new SimpleIntMessage(SimpleIntMessage.op_type.ALL_createUser,1);
			createMessage.setResult(-99);
						
			if (msg.getUser(0).getID().isEmpty() == false)
			{
				System.out.println("UIP@Server: (handleCreateUser) - create user with ID " + msg.getUser(0).getID());
				create_result = db.createUser(msg.getUser(0));
				switch(create_result)
				{
					case 1: // Success
					{
						System.out.println("UIP@Server: (handleCreateUser) user " + msg.getUser(0).getID() + " created successfully.");
						createMessage.setResult(1);
						break;	
					}
					case -1: // User already exists
					{
						System.out.println("UIP@Server: (handleCreateUser) - User " + msg.getUser(0).getID() + " already exists!");
						createMessage.setResult(-1);
						break;
					}
					default: // Error
					{
						System.out.println("UIP@Server: (handleCreateUser) - ERROR!!! query result not 1 or -1...");
						createMessage.setResult(0);
					}
				}
			}
			// Send message back to client
			client.sendToClient(createMessage);
		}
		catch (IOException e)
		{
			System.out.println("UIP@Server: (handleCreateUser) IOException!.");
		}
	}
//=========================================================================================================================
	/**
	 * Handles a message from the client regarding a new borrow for a copy. 
	 * @author Alon Shahaf
	 * @Date 10.01.2013
	 * @param client the connection to the client
	 * @param bmsg the borrow message from the client
	 */
	public void handleLibrarianBorrowCopy(ConnectionToClient client, BorrowMessage bmsg)
	{
		BookCopy bcopy = bmsg.getCopy();
		User	 buser = bmsg.getBorrow_user();
		boolean	 con_flag = false;
		
		System.out.println("UIP@Server: (handleLibrarianBorrowCopy) New borrow request from "+client.getInfo("USER")+"@"+ client.getInetAddress().getHostAddress() + ":  "+buser.getID()+"("+buser.getFname()+") wants copy number " + bcopy.getCopyID());
		try 
		{
			// Prepare return message
			SimpleIntMessage borrowMessage = new SimpleIntMessage(SimpleIntMessage.op_type.LIBRARIAN_borrowCopy,1);
			borrowMessage.setResult(-99);
			
			// Get subscriber details
			int[] buser_sandp = db.getUserPermissionAndStatus(buser.getID());
			
			// Check if this user exists
			if ((buser_sandp[0] == -1) && (buser_sandp[1] == -1))
			{
				borrowMessage.setResult(-8);			// No such user
			}
			else if (( buser_sandp[0] != 3) && (buser_sandp[0] != 5))
			{
				borrowMessage.setResult(-9);		// User is not a a subscriber!	
			}
			// Check subscriber status (if locked)
			else if (buser_sandp[1] == 2)
			{
				borrowMessage.setResult(-1);			// User is locked!
			}
			else
			{
				// Check subscriber permission
				if (buser_sandp[0] == 5)
				{
					borrowMessage.setResult(-2);		// User is suspended!	
				}
				else
				{
					// Check if the subscriber has this book already
					int isBorrowed = db.isBorrowedTo(buser.getID(), bcopy.getCopyOfISBN());
					if (isBorrowed == -1)
					{
						borrowMessage.setResult(-3);		// User already borrowing this book!	
					}
					else if (isBorrowed == -99) {}			// Query error
					else // isBorrowed == 1 (not borrowed by the user
					{	
						// Check that this copy is not lost
						int isLost = db.isLost(bcopy.getCopyID());
						int isTaken;
						if (isLost > 0)
						{
							borrowMessage.setResult(-10);	// This copy is lost!
						}
						// Check that this copy is not taken
						else if((isTaken = db.isCopyTaken(bcopy.getCopyID())) == -1)
						{
							borrowMessage.setResult(-4);	// This copy is already borrowed!	
						}
						else if (isTaken == -99) {}			// Query error
						else
						{
							// Check if this book has orders
							int num_of_orders = db.getNumberOfOrders(bcopy.getCopyOfISBN());
							if (num_of_orders == -99) {}	// Query error
							else
							{
								if (num_of_orders > 0)
								{
									// Check if the borrowing user is the first user in the order queue.
									int inqueue = db.isUserFirstInOrderQueue(buser.getID(),bcopy.getCopyOfISBN());
									if (inqueue == -99) {}
									else if (inqueue == -1)
									{
										borrowMessage.setResult(-5);	// There are earlier orders for this book!
									}
									else
									{
										// This user is the first in queue, allow him to borrow and delete his order.
										int del_order = db.deleteOrder(buser.getID(), bcopy.getCopyOfISBN());
										if (del_order == -99) {}
										else if (del_order == -1)
										{
											borrowMessage.setResult(-6);	// Unable to delete user's order. aborting!
										}
										else	// User's order was deleted, we can create a new borrow for him.
										{
											con_flag = true;				// Raise continue flag to be cached later in next if statement.
										}
									}
								}
								if ((num_of_orders == 0) || (con_flag))	// Borrow is OK for both of these conditions
								{
									// Check if this book is reported "Wanted"
									int isWanted = db.isBookWanted(bcopy.getCopyOfISBN());
									if (isWanted == -99) {}		// Query error
									else
									{
										boolean bwanted = false;
										if (isWanted == 1) bwanted = true;
										System.out.println("UIP@Server: (handleLibrarianBorrowCopy) Creating borrow!");
										int createBorrow = db.createBorrow(buser.getID(),bcopy.getCopyID(),bcopy.getCopyOfISBN(),bwanted);
										
										if (createBorrow == 1)
											borrowMessage.setResult(1);	// Borrow OK!
									}	
								}	// End of if - no orders OR user had order in top position at the queue, which was deleted
							}
						}	// End of if - copy isn't taken
					}	// Not already borrowed by the user
				}	// The user isn't suspended check
			}	// The user isn't locked check
			
			// Send message back to client
			client.sendToClient(borrowMessage);
		}
		catch (Exception e) 
		{
			System.out.println("UIP@Server: (handleLibrarianBorrowCopy) Exception: " + e);
		}
	}
	
//=========================================================================================================================
	/**
	 * Handles a message from the client regarding a manual extension for an existing borrow. 
	 * @author Alon Shahaf
	 * @Date 10.01.2013
	 * @param client the connection to the client
	 * @param rec_msg the manual extension message from the client
	 */
	public void handleLibrarianManualExtension(ConnectionToClient client,
			ManualExtMessage rec_msg) 
		{
			int m_ext_res = -99;
			System.out.println("UIP@Server: (handleLibrarianManualExtension) - Manual Ext. started.");
			// Prepare return message
			SimpleIntMessage mExtMSG = new SimpleIntMessage(SimpleIntMessage.op_type.LIBRARIAN_manualExt,1);
			mExtMSG.setResult(-99);
			
			// Unpack received message
			int borrow_num = rec_msg.getBorrow_num();
			Date new_end_date = rec_msg.getNew_end_date();
			
			m_ext_res = db.manualExtension(borrow_num,new_end_date,(String) client.getInfo("USER"));
			switch(m_ext_res)
			{
				case 1: // Success
				{
					mExtMSG.setResult(1);
					break;
				}
				case -1: // No such borrow
				{
					mExtMSG.setResult(-1);
					break;
				}
				case -3: // Not allowed to extend "Wanted" books.
				{
					mExtMSG.setResult(-3);
					break;
				}					
			}
			// Send message back to client
			try 
			{
				client.sendToClient(mExtMSG);
			}
			catch (IOException e) 
			{
				System.out.println("UIP@Server: (handleLibrarianManualExtension) - IOException!");
			}	
		}
//=========================================================================================================================
	/**
	 * Handles a message from the client regarding an edit of a user 
	 * @author Tali Pisarev
	 * @Date 10.01.2013
	 * @param client the connection to the client
	 * @param UsersMSG the edit message from the client
	 */
	public void handleLibrarianEditUser (ConnectionToClient client, UsersMSG msg)
	{
		
		int edit_result = -99;

		try 
		{	
			// Prepare return message
			SimpleIntMessage createMessage = new SimpleIntMessage(SimpleIntMessage.op_type.EditUser,1);
			createMessage.setResult(-99);
						
			if (msg.getUser(0).getID().isEmpty() == false)
			{
				System.out.println("UIP@Server: (handleLibrarianEditUser) - edit user with ID " + msg.getUser(0).getID());
				edit_result = db.libEditUser(msg.getUser(0));
				switch(edit_result)
				{
					case 1: // Success
					{
						System.out.println("UIP@Server: (handleLibrarianEditUser) user " + msg.getUser(0).getID() + " updated successfully.");
						createMessage.setResult(1);
						break;	
					}

					default: // Error
					{
						System.out.println("UIP@Server: (handleLibrarianEditUser) - ERROR!!! query result not 1 or -1...");
						createMessage.setResult(0);
					}
				}
			}
			// Send message back to client
			client.sendToClient(createMessage);
		}
		catch (IOException e)
		{
			System.out.println("UIP@Server: (handleCreateUser) IOException!.");
		}
	}
		
//==============================================================================================
	//librarian search user
	public void handleLibrarianSearchUserRequest( ConnectionToClient client , String user )
	{
		try
		{
			LibrarianSearchUserMessage resultSearchUserMsg =new LibrarianSearchUserMessage(user) ;
			
			resultSearchUserMsg = db.searchUser(client, user);
		
			client.sendToClient(resultSearchUserMsg);
			
		}
		catch(IOException e)
		{
			System.out.println("Librarian search user Query failed.");
		}
	
		
	}
	
//================================================================================================
	/**
	 * @author Tali Pisarev
	 * @Date 07.01.2013
	 */	
	//Librarian Add Book
	public void handleLibrarianAddBookRequest( ConnectionToClient client , LibrarianAddBookMessage labm )
	{
		try
		{
			System.out.println("ADD NEW BOOK");
			LibrarianAddBookMessage AddBook_msg = new LibrarianAddBookMessage();
			int result = db.libAddBook(client,labm);
			AddBook_msg.setQueryLibAddBookResult(result);
			client.sendToClient(AddBook_msg);
			
		}
		catch(IOException e)
		{
			System.out.println("ERROR IN ADD NEW BOOK");
		}
	
		
	}
//==============================================================================================================	
	/**
	 * @author Tali Pisarev
	 * @Date 08.01.2013
	*/

	public void handleLibrarianEditBookRequest( ConnectionToClient client , LibrarianEditBookMessage edit_msg )
	{
			try
			{
				System.out.println("UIP@Server: (handleLibrarianEditBookRequest) ServerUIP > try query");
				LibrarianEditBookMessage editBookMsg = new LibrarianEditBookMessage();
				int res_msg = db.LibrarianEdiBook( client , edit_msg );
				System.out.println(res_msg);
				editBookMsg.setQueryLibEditBookResult(res_msg);
				client.sendToClient(editBookMsg);
			}
			catch(IOException e)
			{
				System.out.println("UIP@Server: (handleLibrarianSearchBookRequest) Librarian search book Query failed.");
			}
	}	

//==============================================================================================
//librarian search Copy
/**
 * @author Tali Pisarev
 * @Date 09.01.2013
*/
	public void handleLibrarianSearchCopyRequest( ConnectionToClient client , String copyID )
	{
			try
			{
				LibrarianSearchCopyMessage resultSearchCopyMsg = new LibrarianSearchCopyMessage(copyID) ;
				
				resultSearchCopyMsg = db.librarianSearchCopy(client, copyID);
			
				client.sendToClient(resultSearchCopyMsg);
				
			}
			catch(IOException e)
			{
				System.out.println("Librarian search copy Query failed.");
			}
		
			
	}
//================================================================================================
/**
 * @author Tali Pisarev
 * @Date 10.01.2013
 */	
		//Librarian Add Book
	public void handleLibrarianAddCopyRequest( ConnectionToClient client , LibrarianAddCopyMessage lacm )
	{
			try
			{
				System.out.println("ADD NEW Copy");
				LibrarianAddCopyMessage AddCopy_msg = new LibrarianAddCopyMessage();
				int result = db.libAddCopy(client,lacm);
				AddCopy_msg.setQueryLibAddCopyResult(result);
				client.sendToClient(AddCopy_msg);
				
			}
			catch(IOException e)
			{
				System.out.println("ERROR IN ADD NEW BOOK");
			}
		
			
	}
//==============================================================================================================	
/**
* @author Tali Pisarev
* @Date 08.01.2013
*/

	public void handleLibrarianEditCopyRequest( ConnectionToClient client , LibrarianEditCopyMessage edit_msg )
	{
				try
				{
					System.out.println("UIP@Server: (handleLibrarianEditCopyRequest) ServerUIP > try query");
					LibrarianEditCopyMessage editCopyMsg = new LibrarianEditCopyMessage();
					int res_msg = db.LibrarianEdiCopy( client , edit_msg );
					System.out.println(res_msg);
					editCopyMsg.setQueryLibEditCopyResult(res_msg);
					client.sendToClient(editCopyMsg);
				}
				catch(IOException e)
				{
					System.out.println("UIP@Server: (handleLibrarianSearchBookRequest) Librarian search book Query failed.");
				}
	}	
//================================================================================================================
	/**
	* @author Tali Pisarev
	* @Date 11.01.2013
	* This method handles books subjects request  
	*/
	
	public void handleLibrarianSubjectBooksRequest(ConnectionToClient client, LibrarianSubjectMessage bookSubMsg)
	{
		try
		{
			LibrarianSubjectMessage bookSubject_msg = new LibrarianSubjectMessage();
			bookSubject_msg = db.getBooksSubjectsByISBN(client,bookSubMsg);
			client.sendToClient(bookSubject_msg);
			System.out.println("get Books subjects Query OK ");
		}
		catch(IOException e)
		{
			System.out.println("get Books subjects Query failed ");
		}
		
	}

//================================================================================================================
/**
* @author Tali Pisarev
* @Date 12.01.2013
* This method handles books subjects request  
*/
		
		public void handleLibrarianRemoveCopyRequest(ConnectionToClient client, LibrarianRemoveCopyMessage removeCopyMsg)
		{
			try
			{
				LibrarianRemoveCopyMessage removeCopy_msg = new LibrarianRemoveCopyMessage();
				int resultRemoveCopy = db.removeCopy(client,removeCopyMsg);
				removeCopy_msg.setQueryLibRemoveCopyResult(resultRemoveCopy);
				client.sendToClient(removeCopy_msg);
				System.out.println("Remove Copy Query OK ");
			}
			catch(IOException e)
			{
				System.out.println("Remove Copy Query failed ");
			}
			
		}	
//================================================================================================================	
/**
* @author Tali Pisarev
* @Date 12.01.2013
* This method handles books subjects request  
*/
				
	public void handleLibrarianRemoveBookRequest (ConnectionToClient client, LibrarianRemoveBookMessage removeBookMsg)
	{
		try
		{
			LibrarianRemoveBookMessage removeBook_msg = new LibrarianRemoveBookMessage();
			int removeBookresult = db.removeBook(client,removeBookMsg);
			removeBook_msg.setQueryLibRemoveBookResult(removeBookresult);
			client.sendToClient(removeBook_msg);
			System.out.println("Remove Book Query OK ");
		}
		catch(IOException e)
		{
			System.out.println("Remove Book Query failed ");
		}
					
	}	
	
//================================================================================================================	
/**
* @author Tali Pisarev
* @Date 15.01.2013
* This method handles books subjects request  
*/
					
	public void handleLibrarianReturnBookRequest (ConnectionToClient client, LibrarianReturnBookMessage returnBookMsg )
	{
		try
		{
			LibrarianReturnBookMessage returnBook_msg = new LibrarianReturnBookMessage();
			Date actualDate=clk.getTime();
			int returnBookResult = db.returnBook(client,returnBookMsg,actualDate);
			returnBook_msg.setQueryLibReturnBookResult(returnBookResult);
			client.sendToClient(returnBook_msg);
			System.out.println("Return Book Query OK ");
		}
		catch(IOException e)
		{
			System.out.println("Return Book Query failed ");
		}
						
	}
//================================================================================================================
  /**
	* @author Roman Factorovich
	* @Date 16.01.2013
	* This method handles Activity Report requested by Manager  
	*/
	public void handleActivityReportRequest(ConnectionToClient client,ActivityReportMessage Activity_msg )
	{
		try
		{
			
			Date actualDate = clk.getTime();
			Activity_msg = db.getActivityReports(Activity_msg , actualDate);
			
			client.sendToClient(Activity_msg);
			System.out.println("handleActivityReportRequest : getActivityReports Query OK ");
		}
		catch(IOException e)
		{
			System.out.println("handleActivityReportRequest : getActivityReports Query failed ");
		}
	
	}
	
//================================================================================================================
	  /**
		* @author Roman Factorovich
		* @Date 16.01.2013
		* This method handles Activity Report requested by Manager  
		*/
		public void handleNewActivityReportRequest(ConnectionToClient client,ActivityReportMessage Activity_msg )
		{
			try
			{
				Date actualDate = clk.getTime();
				Activity_msg = db.getNewActivityReport(Activity_msg , actualDate);
				client.sendToClient(Activity_msg);
				System.out.println("handleNewActivityReportRequest : getNewActivityReport Query OK ");
			}
			catch(IOException e)
			{
				System.out.println("handleActivityReportRequest : getNewActivityReport Query failed ");
			}
		}
//================================================================================================================
		/**
		 * Handles a new PDF file upload from a client 
		 * @author Alon Shahaf
		 * @Date 10.01.2013
		 * @param client the connection to the client
		 * @param toc_msg the TOC message from the client
		 */
	public void handlePdfUpload(ConnectionToClient client, TOCMessage toc_msg)
	{
		System.out.println("UIP@Server: (handlePdfUpload) got TOC message for ISBN = "+toc_msg.getIsbn());
		
		SimpleIntMessage returnMessage = new SimpleIntMessage(SimpleIntMessage.op_type.LIBRARIAN_tocUpload,1);
		returnMessage.setResult(-99);
		
		try
		{
			toc_msg.setSuccess(true);
			Save save = new Save(toc_msg.getMyfile(),OBLSettings.TOC_SERVER_PATH);
			System.out.println("UIP@Server: (handlePdfUpload) File saved on Hard Disk.");
			int db_save = db.saveTOCFileName(toc_msg.getIsbn(), save.getFf().getName());
			System.out.println("UIP@Server: (handlePdfUpload) save on DB result = "+db_save);
			returnMessage.setResult(1);			
			client.sendToClient(returnMessage);
			System.out.println("UIP@Server: (handlePdfUpload) Query OK ");
		}
		catch(IOException e)
		{
			System.out.println("UIP@Server: (handlePdfUpload) Query failed ");
		}
		
	}
//================================================================================================================
	/**
	 * Handles a TOC download message from the client 
	 * @author Alon Shahaf
	 * @Date 10.01.2013
	 * @param client the connection to the client
	 * @param req_msg the TOC download message from the client
	 */
	public void handlePdfDownload(ConnectionToClient client, RequestTOCMessage req_msg)
	{
		System.out.println("UIP@Server: (handlePdfDownload) got TOC REQUEST message for ISBN = "+req_msg.getIsbn());
		
		try
		{
			TOCMessage toc_msg = new TOCMessage();
			toc_msg.setSuccess(false);
			// Check if this book has TOC
			String toc_file = null;
			toc_file = db.hasTOC(req_msg.getIsbn()); 
			System.out.println("UIP@Server: (handlePdfDownload) hasTOC result = "+toc_file);
			
			if (toc_file != null)
			{
				// Read file into toc_msg
				String strFilePath = OBLSettings.TOC_SERVER_PATH + toc_file;
				File file = null; 
 
		    	file = new File(strFilePath);
	        	Browse b = new Browse(file);
				if (b.getFile() != null)
				{	
					toc_msg.setMyfile(b.getFile());		// Put this file into the message
					toc_msg.setSuccess(true);			// Mark as success
					System.out.println("UIP@Server: (handlePdfDownload) Ready to send TOC file!");
			    }
			}
			client.sendToClient(toc_msg);
		}
		catch(IOException e)
		{
			System.out.println("UIP@Server (handlePdfDownload) TOC Request handling failed.");
		}
	}
//================================================================================================================
	/**
	 * Handles a delete TOC message from the client regarding deletion of a TOC from the server. 
	 * @author Alon Shahaf
	 * @Date 10.01.2013
	 * @param client the connection to the client
	 * @param del_msg the delete TOC message from the client
	 * @return 1 for success, -99 otherwise.
	 */
		public int handlePdfDelete(ConnectionToClient client, DeleteTOCMessage del_msg)
		{
			SimpleIntMessage returnMessage = new SimpleIntMessage(SimpleIntMessage.op_type.LIBRARIAN_tocUpload,1);
			returnMessage.setResult(-99);
			
			int del_result = -99;
			try
			{
				del_result = db.deleteTOC(del_msg.getIsbn());
				System.out.println("UIP@Server (handlePdfDelete) Query OK ");
				if (del_result == 1)
				{
					returnMessage.setResult(1);
					// Delete file from Hard Disk
					try
					{
						File file = new File(OBLSettings.TOC_SERVER_PATH + del_msg.getIsbn()+".pdf");
						if (file.delete())
							System.out.println("UIP@Server (handlePdfDelete) Deleted TOC file - " + OBLSettings.TOC_SERVER_PATH + del_msg.getIsbn()+".pdf");
						else
							System.out.println("UIP@Server (handlePdfDelete) Could not delete TOC file - " + OBLSettings.TOC_SERVER_PATH + del_msg.getIsbn()+".pdf");
					}
					catch (Exception e)	
					{
						System.out.println("UIP@Server (handlePdfDelete) Unable to delete TOC file - " + OBLSettings.TOC_SERVER_PATH + del_msg.getIsbn()+".pdf");		
					}
				}
				client.sendToClient(returnMessage);
			}
			catch(IOException e)
			{
				System.out.println("UIP@Server (handlePdfDelete) Query failed ");
			}
			return del_result;
		}
//================================================================================================================		
		
}//class
